/* Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 *    http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * Contributor: xucaiming <719260170@qq.com>
 * Maintainer: xucaiming <719260170@qq.com>
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "pvmp3decoder_api.h"

#define PVMP3DEC_OBUF_SIZE    (8 * 1024)

int main(int argc, char **argv)
{
    FILE *fin = NULL;
    FILE *fout = NULL;
    tPVMP3DecoderExternal *config = NULL;
    uint32_t msize;
    void *in_ptr = NULL;
    void *out_ptr = NULL;
    void *dbuf = NULL;
    int infile_len;
    ERROR_CODE ecode;
    int32 offset = 0;

    if (argc != 3) {
        printf("Usage: mp3_test [input source] [output source]\n");
        printf("example: ./mp3_test input.mp3 output.pcm\n");
        goto err0;
    }
    if ((argv[1] == NULL) || (argv[2] == NULL)) {
        printf("input parameter error\n");
        goto err0;
    }

    fin = fopen(argv[1], "r");
    if (!fin) {
        printf("open input file failed\n");
        goto err0;
    }

    fout = fopen(argv[2], "w");
    if (!fout) {
        printf("open output file failed\n");

        goto err1;
    }

    fseek(fin, 0, SEEK_END);
    infile_len = ftell(fin);
    fseek(fin, 0, SEEK_SET);
    in_ptr = malloc(infile_len + 1);
    if (!in_ptr) {
        printf("malloc mem failed\n");
        goto err2;
    }
    memset(in_ptr, 0, infile_len + 1);
    fread(in_ptr, 1, infile_len, fin);

    msize = pvmp3_decoderMemRequirements();
    dbuf = malloc(msize);
    if (!dbuf) {
        printf("malloc dbuf failed\n");
        goto err3;
    }
    memset(dbuf, 0, msize);

    out_ptr = malloc(PVMP3DEC_OBUF_SIZE);
    if (!out_ptr) {
        printf("malloc out_ptr failed\n");
        goto err4;
    }
    memset(out_ptr, 0, PVMP3DEC_OBUF_SIZE);

    config = (tPVMP3DecoderExternal *)(intptr_t)malloc(sizeof(tPVMP3DecoderExternal));
    if (!config) {
        printf("malloc tPVMP3DecoderExternal failed\n");
        goto err5;
    }
    memset(config, 0, sizeof(tPVMP3DecoderExternal));

    /* 初始化解码器 */
    pvmp3_InitDecoder(config, dbuf);
    config->crcEnabled    = 0;
    config->equalizerType = flat;

    config->inputBufferCurrentLength = infile_len;
    config->pInputBuffer             = (uint8 *)(intptr_t)in_ptr;
    config->inputBufferMaxLength     = 0;
    config->inputBufferUsedLength    = 0;
    config->outputFrameSize          = infile_len / sizeof(int16_t);
    config->pOutputBuffer = (int16 *)(intptr_t)out_ptr;


    /* 因为MP3格式音频文件一帧数据不超过8K，所以源库对输入数据的长度限制到8K以内，也就是解码一帧mp3数据 */
    while (offset < infile_len) {
        ecode = pvmp3_framedecoder(config, dbuf);
        if (ecode != NO_DECODING_ERROR) {
            printf("Decoder mp3 file error\n");
            goto err6;
        }


        fwrite(out_ptr, 1, config->outputFrameSize * sizeof(int16_t), fout);
        memset(out_ptr, 0, PVMP3DEC_OBUF_SIZE);
                        
        printf("audio inputBufferMaxLength=%d\n", config->inputBufferMaxLength);
        printf("audio inputBufferUsedLength=%d\n", config->inputBufferUsedLength);
        printf("audio pInputBuffer=%d\n", config->pInputBuffer);
        printf("audio inputBufferCurrentLength=%d\n", config->inputBufferCurrentLength);
        printf("audio outputFrameSize=%d\n", config->outputFrameSize);
        printf("audio pOutputBuffer=%d\n", config->pOutputBuffer);

        offset += config->inputBufferUsedLength;
        config->inputBufferCurrentLength = infile_len - offset;
        config->pInputBuffer             = (uint8 *)(intptr_t)in_ptr + offset;    
        config->inputBufferMaxLength     = 0;
        config->inputBufferUsedLength    = 0;

    }

    printf("audio channels=%d\n", config->num_channels);
    printf("audio FrameSize=%d\n", config->outputFrameSize);
    printf("audio samplingRate=%d\n", config->samplingRate);
    printf("audio bitRate=%d\n", config->bitRate);

    printf("Decoder mp3 file success\n");
    return 0;

err6:
    free(config);
err5:
    free(out_ptr);
err4:
    free(dbuf);
err3:
    free(in_ptr);
err2:
    fclose(fout);
err1:
    fclose(fin);
err0:
    return -1;
}
